<?php
/**
 * @copyright Copyright(c) 2011 aircheng.com
 * @file direct_alipay.php
 * @brief 支付宝插件类[即时到帐]
 * @author nswe
 * @date 2011-01-27
 * @version 0.6
 * @note
 */
require_once 'plugins/WxpayAPI_php_v3/lib/WxPay.Api.php';
require_once 'plugins/WxpayAPI_php_v3/example/WxPay.JsApiPay.php';
require_once 'plugins/WxpayAPI_php_v3/lib/WxPay.Notify.php';
require_once 'plugins/WxpayAPI_php_v3/example/log.php';

//初始化日志
$logHandler= new CLogFileHandler("backup/logs/pay_wechat/".date('Y-m-d').'.log');
$log = Log::Init($logHandler, 15);

 /**
 * @class direct_alipay
 * @brief 支付宝插件类
 */
class wap_wechat extends paymentPlugin
{
	//支付插件名称
    public $name = '微信端支付';

    /**
     * @brief 构造函数
     * @param $payment_id 支付方式ID
     */
    public function __construct($payment_id)
    {
    	parent::__construct($payment_id);

    	//因为WAP端采用H5单页面，处理略微不一样
    	//同步回调地址
    	$this->callbackUrl         = IUrl::getHost().IUrl::creatUrl("/yunblock/callback/_id/".$payment_id);
    	//回调业务处理地址
    	//$this->serverCallbackUrl   = IUrl::getHost().IUrl::creatUrl("/yunblock/server_callback/_id/".$payment_id);
    	$this->serverCallbackUrl   = IUrl::getHost().'/notify/notify_wechat.php';
    	//中断支付返回
    	$this->merchantCallbackUrl = IUrl::getHost().IUrl::creatUrl("/yunblock/merchant_callback/_id/".$payment_id);
    }

	/**
	 * @see paymentplugin::getSubmitUrl()
	 */
	public function getSubmitUrl()
	{
		return 'https://mapi.alipay.com/gateway.do?_input_charset=utf-8';
	}

	/**
	 * @see paymentplugin::notifyStop()
	 */
	public function notifyStop()
	{
		//echo "success";
	}

	/**
	 * @see paymentplugin::callback()
	 */
	public function callback($callbackData,&$paymentId,&$money,&$message,&$orderNo)
	{
		//微信的回调数据被notify.php中转打包了一次
		if ( isset($GLOBALS['HTTP_RAW_POST_DATA']) ) {
			$xml = $GLOBALS['HTTP_RAW_POST_DATA'];
		} else {
			$xml = $_POST['HTTP_RAW_POST_DATA'];
		}
		$callbackData = WxPayResults::Init($xml);

		Log::INFO("开始回调处理");
		$notify = new PayNotifyCallBack();
		$notify->Handle(false);

		//回传数据处理
		$paymentId = 13;
		$orderNo = $callbackData['out_trade_no'];
		$money   = number_format($callbackData['total_fee'], 2, '.', '');;

		//记录回执流水号
		if(isset($callbackData['transaction_id']) && $callbackData['transaction_id'])
		{
			$this->recordTradeNo($orderNo,$callbackData['transaction_id']);
		}

		if ( $notify->GetReturn_code() == 'SUCCESS' ) {
			Log::INFO('此订单支付状态正常');
			return true;
		} else {
			return false;
		}
	}

	/**
	 * @see paymentplugin::serverCallback()
	 */
	public function serverCallback($callbackData,&$paymentId,&$money,&$message,&$orderNo)
	{
		return $this->callback($callbackData,$paymentId,$money,$message,$orderNo);
	}

	/**
	 * @see paymentplugin::getSendData()
	 */
	public function getSendData($payment)
	{
		$return = array();

		//基本参数
		$return['service'] = 'alipay.wap.create.direct.pay.by.user';
		$return['partner'] = $payment['M_PartnerId'];
		$return['seller_id'] = $payment['M_PartnerId'];
		$return['payment_type'] = 1;
		$return['return_url'] = $this->callbackUrl;
		$return['notify_url'] = $this->serverCallbackUrl;
		$return['_input_charset'] = 'utf-8';

		//业务参数
		$return['out_trade_no'] = $payment['M_OrderNO'];//商户订单号，商户网站订单系统中唯一订单号，必填
		$return['subject'] = $payment['R_Name'];//订单名称，必填
		$return['total_fee'] = number_format($payment['M_Amount'], 2, '.', '');//付款金额，必填
		$return['show_url'] = 'http://www.yunguostore.com/index.php';//收银台页面上，商品展示的超链接，必填
		// $return['app_pay'] = 'Y';//启用能唤醒钱包APP支付宝
		$return['body'] = '';//可空

		//除去待签名参数数组中的空值和签名参数
		$para_filter = $this->paraFilter($return);

		//对待签名参数数组排序
		$para_sort = $this->argSort($para_filter);

		//生成签名结果
		$mysign = $this->buildMysign($para_sort, $payment['M_PartnerKey']);

		//签名结果与签名方式加入请求提交参数组中
		$return['sign'] = $mysign;
		$return['sign_type'] = 'MD5';

		return $return;
	}

	public function doPay($sendData)
	{
		//①、获取用户openid
		$tools = new JsApiPay();
		//$openId = $tools->GetOpenid();
		$userinfo = ICookie::get('wechat_userinfo');
		$openId = $userinfo['openid'];
		//②、统一下单
		$input = new WxPayUnifiedOrder();
		$input->SetBody("test");
		$input->SetAttach("test");
		$input->SetOut_trade_no($sendData['out_trade_no']);
		$input->SetTotal_fee($sendData['total_fee']*100);
		$input->SetTime_start(date("YmdHis"));
		$input->SetTime_expire(date("YmdHis", time() + 600));
		$input->SetGoods_tag("test");
		$input->SetNotify_url($sendData['notify_url']);
		$input->SetTrade_type("JSAPI");
		$input->SetOpenid($openId);
		$order = WxPayApi::unifiedOrder($input);
		Log::INFO($input->ToXml());
		//echo '<font color="#f00"><b>统一下单支付单信息</b></font><br/>';
		//printf_info($order);
		$jsApiParameters = $tools->GetJsApiParameters($order);
		//获取共享收货地址js函数参数
		//$editAddress = $tools->GetEditAddressParameters();

		$success_callbackurl = IUrl::creatUrl('/site/index/view/mallView/page/'.urlencode('/yunsimple/pay_success'));
		$cancel_callbackurl = IUrl::creatUrl();
		$fail_callbackurl = IUrl::creatUrl();

		Log::INFO("begin doPay");
		Log::INFO($jsApiParameters);

		echo <<< OEF
		<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
		<html xmlns="http://www.w3.org/1999/xhtml">
			<head></head>
			<body>
			</body>
    <script type="text/javascript">
	//调用微信JS api 支付
	function jsApiCall()
	{
		WeixinJSBridge.invoke(
			'getBrandWCPayRequest',
			$jsApiParameters,
			function (res) {
				WeixinJSBridge.log(res.err_msg);
				//alert(res.err_code+res.err_desc+res.err_msg);
				if (res.err_msg == 'get_brand_wcpay_request:ok') {
					//支付成功后跳转的地址
					window.location.href='$success_callbackurl';
	            }else if (res.err_msg == 'get_brand_wcpay_request:cancel') {
	              	alert('请尽快完成支付哦！');
					window.location.href='$cancel_callbackurl';
	            }else if (res.err_msg == 'get_brand_wcpay_request:fail') {
	              	//alert('支付失败');
	              	window.location.href='$fail_callbackurl';
	            }else {
	              	alert('意外错误');
	            }
			}
		);
	}

	function callpay()
	{
		if (typeof WeixinJSBridge == "undefined"){
		    if( document.addEventListener ){
		        document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
		    }else if (document.attachEvent){
		        document.attachEvent('WeixinJSBridgeReady', jsApiCall);
		        document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
		    }
		}else{
		    jsApiCall();
		}
	}
	window.onload = function(){
		callpay();
	};
	</script>
		</html>
OEF;
	}

	/**
	 * 除去数组中的空值和签名参数
	 * @param $para 签名参数组
	 * return 去掉空值与签名参数后的新签名参数组
	 */
	private function paraFilter($para)
	{
		$para_filter = array();
		foreach($para as $key => $val)
		{
			if($key == "sign" || $key == "sign_type" || $val == "")
			{
				continue;
			}
			else
			{
				$para_filter[$key] = $para[$key];
			}
		}
		return $para_filter;
	}

	/**
	 * 对数组排序
	 * @param $para 排序前的数组
	 * return 排序后的数组
	 */
	private function argSort($para)
	{
		ksort($para);
		reset($para);
		return $para;
	}

	/**
	 * 生成签名结果
	 * @param $sort_para 要签名的数组
	 * @param $key 支付宝交易安全校验码
	 * @param $sign_type 签名类型 默认值：MD5
	 * return 签名结果字符串
	 */
	private function buildMysign($sort_para,$key,$sign_type = "MD5")
	{
		//把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
		$prestr = $this->createLinkstring($sort_para);
		//把拼接后的字符串再与安全校验码直接连接起来
		$prestr = $prestr.$key;
		//把最终的字符串签名，获得签名结果
		$mysgin = md5($prestr);
		return $mysgin;
	}

	/**
	 * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
	 * @param $para 需要拼接的数组
	 * return 拼接完成以后的字符串
	 */
	private function createLinkstring($para)
	{
		$arg  = "";
		foreach($para as $key => $val)
		{
			$arg.=$key."=".$val."&";
		}

		//去掉最后一个&字符
		$arg = trim($arg,'&');

		//如果存在转义字符，那么去掉转义
		if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
		{
			$arg = stripslashes($arg);
		}

		return $arg;
	}

	/**
	 * @param 获取配置参数
	 */
	public function configParam()
	{
		$result = array(
			'M_PartnerId'  => '合作者身份（PID）',
			'M_PartnerKey' => '安全校验码（Key）',
			'M_Email'      => '登录账号',
		);
		return $result;
	}
}

class PayNotifyCallBack extends WxPayNotify
{
	//查询订单
	public function Queryorder($transaction_id)
	{
		$input = new WxPayOrderQuery();
		$input->SetTransaction_id($transaction_id);
		$result = WxPayApi::orderQuery($input);
		Log::INFO("query:" . json_encode($result));
		if(array_key_exists("return_code", $result)
				&& array_key_exists("result_code", $result)
				&& $result["return_code"] == "SUCCESS"
				&& $result["result_code"] == "SUCCESS")
		{
			return true;
		}
		return false;
	}

	//重写回调处理函数
	public function NotifyProcess($data, &$msg)
	{
		Log::INFO("call back:" . json_encode($data));
		$notfiyOutput = array();

		if(!array_key_exists("transaction_id", $data)){
			$msg = "输入参数不正确";
			return false;
		}
		//查询订单，判断订单真实性
		if(!$this->Queryorder($data["transaction_id"])){
			$msg = "订单查询失败";
			return false;
		}
		return true;
	}
}